package org.juiceshop.groovy.orientdb;

import groovy.lang.Closure;

import java.util.List;

import org.codehaus.groovy.runtime.DefaultGroovyMethods;

import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.index.OIndex;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.metadata.schema.OProperty;
import com.orientechnologies.orient.core.metadata.schema.OSchema;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.query.nativ.OQueryContextNative;
import com.orientechnologies.orient.core.record.impl.ODocument;


public class OrientDbExtensions {
	
	private static boolean _initialized = false;
	
	public static void init() {
		if (!_initialized) _initialized=true; else return;
//		DefaultGroovyMethods.mixin(ODocument.class,ODocumentExtensions.class);
//		DefaultGroovyMethods.mixin(OIndex.class,OIndexExtensions.class);
//		DefaultGroovyMethods.mixin(OQueryContextNative.class,OQueryContextNativeExtensions.class);		
//		DefaultGroovyMethods.mixin(OSchema.class,OSchemaExtensions.class);		
//		DefaultGroovyMethods.mixin(OClass.class,OClassExtensions.class);		
//		DefaultGroovyMethods.mixin(OProperty.class,OPropertyExtensions.class);
	}
	
	
		
	
	public static Object get(final ODocument doc, final String name) {
		if (doc.containsField(name)) return doc.field(name);
		throw new IllegalArgumentException("Missing field: "+name);
	}
		
	public static Object set(final ODocument doc, final String name, final Object value) {
		return doc.field(name,value);
	}

	///// OIndex extensions
	
	public static Object getAt(OIndex<?> idx, Object indexValue) {
		return idx.get(indexValue);
	}
	
	public static Object getAt(OIndex<?> idx, String indexValue) {
		return getAt(idx,(Object)indexValue);
	}
		
//		public static ODocument getAt(OIndex<?> idx, Object indexValue) {
//			Object result = idx.get(indexValue);
//			if (result instanceof OIdentifiable) {
//				return ((OIdentifiable)result).getRecord();
//			}
//			else if (result instanceof List<?>) {
//				@SuppressWarnings("unchecked")
//				List<OIdentifiable> list = (List<OIdentifiable>)result;
//				return list.size()>0 ? (ODocument)list.get(0).getRecord() : null ;
//			} else {
//				throw new RuntimeException("Unexpected result type: "+result);
//			}
//		}
//		
//		public static ODocument getAt(final OIndex<?> idx, final String indexValue) {
//			return getAt(idx,(Object)indexValue);
//		}
	

	////// OQueryContextNative extensions
			
	public static OQueryContextNative get (final OQueryContextNative ctx, final String fieldName) {
		return ctx.field(fieldName);
	}

	///// OSchema extensions

	public static OClass dbClass (OSchema schema, String name, Closure<Void> closure) {
		return Utils.callClosure(closure, schema.createClass(name));
	}
	
	public static OClass dbClass (OSchema schema, String name) {
		return dbClass(schema,name,null);
	}
	
	///// OClass Extensions
	
	public static OProperty property (OClass dbClass, String name, OType type) {
		return dbClass.createProperty(name, type);
	}
	
	public static OProperty property (OClass dbClass, String name, OType type, Closure<Void> closure) {
		return Utils.callClosure(closure, property(dbClass,name,type));
	}

	///// OProperty extensions

	public static OIndex<?> index (OProperty prop, OClass.INDEX_TYPE type) {
		return prop.createIndex(type);
	}
	
	public static OIndex<?> index (OProperty prop) {
		return index(prop,OClass.INDEX_TYPE.NOTUNIQUE);
	}
	
	public static OIndex<?> indexUnique (OProperty prop) {
		return index(prop,OClass.INDEX_TYPE.UNIQUE);
	}


} 
